import { Provide,Inject } from '@midwayjs/decorator';
import { Repository } from 'typeorm';
import { In } from 'typeorm/find-options/operator/In';
import { DBBase } from '../base/DBBase';
import { Constant } from '../common/Constant';
import { ErrCode } from '../common/ErrCode';
import { Tools } from '../common/Tools';
import { UserBindDTO, UserEquities, UserLevel, UserLoginDTO, UserStatus, UserWechatLoginDTO } from '../dto/user.dto';
import { CurrencyLog } from '../entity/CurrencyLog.entity';
import { UserInfo } from '../entity/user.entity';
import { UserPartner } from '../entity/userPartner.entity';
import { IPagingData } from '../interfaces/IBase.interface';
import { UserPartnerStatus } from '../interfaces/IPartner.interface';
import { IBaseConfig, SystemConfigType } from '../interfaces/ISystem.interface';
import { CurrencyLogStatus, CurrencyLogType, IEquitiesData, IUserClientData, IUserPartnerProject, WechatLoginType } from '../interfaces/IUser.interface';
// import { IWechatLoginData } from '../interfaces/IWechat.interface';
import { PartnerService } from './partner.service';
import { SystemConfigService } from './system.service';
import { WechatService } from './wechat.service';

@Provide()
export class UserService extends DBBase {

  @Inject()
  wechat:WechatService;

  @Inject()
  partnerService:PartnerService;

  @Inject()
  systemConfig:SystemConfigService;

  public async registered(reginfo:UserLoginDTO):Promise<ErrCode>{
      let users:Repository<UserInfo> = await this.Repository({entities:UserInfo});
      let user:UserInfo = await users.findOne({select:['username'],where:{username:reginfo.username}});
      if(!user){
        let reg:UserInfo = new UserInfo();
        reg.regtime = Tools.timestamp;
        reg.lasttime = Tools.timestamp;
        reg.username = reginfo.username;
        reg.password =  Tools.md5(Tools.md5(reginfo.password));
        try{
          await users.insert(reg);
          return ErrCode.USER_REG_SUCCESS;
        }catch(e){
          //将错误 写入日志
          console.log(e);
          return ErrCode.USER_REG_FAIL;
        }
      }else{
        return ErrCode.USER_REG_EXIST;
      }
  }
  
  public async login(info:UserLoginDTO):Promise<ErrCode|UserInfo>{
      let users:Repository<UserInfo> = await this.Repository({entities:UserInfo});
      let user:UserInfo = await users.findOne({select:['id','username','password'],where:{username:info.username}});
      if(!user){
          return ErrCode.USER_NOT_FOUND;
      }else{
        let pwd = Tools.md5(Tools.md5(info.password));
        if(pwd == user.password){
          user.lasttime = Tools.timestamp;
          users.save(user);
          return user;
        }else{
          return ErrCode.USER_LOGIN_FAIL_PWD;
        }
      }
  }

  private async checkUserid(userid):Promise<any>{
    let users:Repository<UserInfo> = await this.Repository({entities:UserInfo});
    let user:UserInfo = await users.findOne({select:['id'],where:{userid:userid}});
    if(user == null){
      return userid;
    }else{
      return await this.checkUserid(Tools.makeRandomNum(10));
    }
  }

  public async getUserOpenid(userid:number):Promise<string|ErrCode>{
    let users:Repository<UserInfo> = await this.Repository({entities:UserInfo});
    let user:UserInfo = await users.findOne({select:['openid'],where:{userid:userid}});
    if(user != null){
      return user.openid;
    }else{
      return ErrCode.USER_NOT_FOUND_OPENID;
    }
  }

  public async getUserinfoById(userid:number[]):Promise<UserInfo[]>{
    let rep:Repository<UserInfo> = await this.Repository({entities:UserInfo});
    let list:UserInfo[] = await rep.find({where:{userid:In(userid)}});
    return list;
  }
  /**绑定用户信息 */
  public async BindUserInfo(userid:number,binddata:UserBindDTO):Promise<ErrCode>{
    let users:Repository<UserInfo> = await this.Repository({entities:UserInfo});
    let user:UserInfo = await users.findOne({where:{userid:userid}});
    if(user != null){
      user.username = binddata.username;
      user.phone = binddata.phone;
      try {
        await users.save(user);
        return ErrCode.USER_BIND_SUCCESS;
      } catch (error) {
        console.error(error);
        return ErrCode.SYSTEM_FAIL;
      }
    }else{
      return ErrCode.USER_NOT_FOUND
    }
  }


  private async AddUpdateUser(openid:string):Promise<ErrCode|IUserClientData>{
    if(openid != null && openid != ""){
      // 获取用户信息 如果 没有用户信息 则创建用户信息  
      let users:Repository<UserInfo> = await this.Repository({entities:UserInfo});
      let user:UserInfo = await users.findOne({where:{openid:openid}});
      let baseConfig:IBaseConfig = await this.systemConfig.getSystemConfig(SystemConfigType.Base_Config);
      if(!user){
        let reg:UserInfo = new UserInfo();
        reg.userid = await this.checkUserid(Tools.makeRandomNum(10));
        reg.openid = openid;
        reg.lasttime = Tools.timestamp;
        reg.regtime = Tools.timestamp;
        reg.currency = baseConfig.Currency_Base;
        reg.username = "";
        reg.phone = "";
        try {
          await users.insert(reg);
        
          let ruser:IUserClientData = {
            userid: reg.userid,
            phone: reg.phone,
            username: reg.username,
            status: UserStatus.NORMAL,
            level: UserLevel.Ordinary,
            equities: UserEquities(0),
            currency:baseConfig.Currency_Base
          }
          return ruser;
        } catch (error) {
          return ErrCode.USER_REG_FAIL;
        }
      }else{
        let projectInfo:IUserPartnerProject = await this.partnerService.getUserPartnerInfo(user.userid);
        let ruser:IUserClientData = {
          userid: user.userid,
          phone: user.phone,
          username: user.username,
          currency:user.currency,
          status: user.status,
          level: user.level,
          equities: UserEquities(user.level),
          project:projectInfo
        }
        
        user.lasttime = Tools.timestamp;
        try {
          users.save(user);
        } catch (error) {
          console.error(error);
          return ErrCode.SYSTEM_FAIL;
        }
        return ruser;
      }
    }else{
      return ErrCode.USER_LOGIN_FAIL_OPENID
    }
  }
  /***微信登录 */
  public async wechatLogin(login:UserWechatLoginDTO):Promise<ErrCode|IUserClientData>{
    switch(login.type){
      case WechatLoginType.OA:
        let result_oa:any = await this.wechat.OALogin(login.code);
        if(typeof(result_oa) == 'number'){
          return result_oa;
        }
        //更新 添加 用户信息
        return await this.AddUpdateUser(result_oa.openid);
        break;
      case WechatLoginType.Small:
        let loginResult:any = await this.wechat.SmallLogin(login.code);
        if(typeof(loginResult) == 'number'){
            return loginResult;
        }
        if(loginResult.errcode != null){
          return loginResult;//ErrCode.WECHAT_ERR_CODE_INVALID;
        }else{
               //更新 添加 用户信息
            return await this.AddUpdateUser(loginResult.openid);
        }
        break;
      default:
        return ErrCode.USER_LOGIN_TYPE_ERR;
    }
  }
    /**获取用户信息 */
    public async getUserInfo(userid:number):Promise<ErrCode|UserInfo>{
      let userRep:Repository<UserInfo> = await this.Repository({entities:UserInfo});
      let user:UserInfo = await userRep.findOne({where:{userid:userid}});
      if(user != null){
        return user;
      }else{
        return ErrCode.USER_NOT_FOUND;
      }
  }
  /**检查权益 */
  public async CheckUserEquities(userid:number):Promise<ErrCode>{
      let userRep:Repository<UserInfo> = await this.Repository({entities:UserInfo});
      let user:UserInfo = await userRep.findOne({select:['level'],where:{userid:userid}});
      if(user != null){
        let equities:IEquitiesData = UserEquities(user.level);
        if(equities.QueryCount < 0){
          return ErrCode.SYSTEM_SUCCESS;
        }else{
          let plist:UserPartner[] =  await this.partnerService.getUserPartnerByStatus(userid,UserPartnerStatus.Paid);
          if(plist.length < equities.QueryCount){
            return ErrCode.SYSTEM_SUCCESS;
          }else{
            return ErrCode.SYSTEM_FAIL;
          }
        }
      }else{
        return ErrCode.SYSTEM_FAIL;
      }
  }
  /**获取合伙点明细 */
  public async getCurrenyList(userid:number,paging:IPagingData):Promise<CurrencyLog[]>{
    let crep:Repository<CurrencyLog> = await this.Repository({entities:CurrencyLog});
    let list:CurrencyLog[] = await crep.find({where:{userid:userid},order:{id:'desc'},skip:((paging.page-1)*paging.limit),take:paging.limit});
    return list;
  }
  /**获取用户货币 */
  public async GetCurrency(userid:number):Promise<number>{
      let userRep:Repository<UserInfo> = await this.Repository({entities:UserInfo});
      let info:UserInfo = await userRep.findOne({where:{userid:userid}});
      if(info != null){
        return info.currency;
      }
      return 0;
  }
  /**增加 用户货币 */
  public async AddCurrency(userid:number[],num:number):Promise<ErrCode>{
    let userRep:Repository<UserInfo> = await this.Repository({entities:UserInfo});
    let info:UserInfo[] = await userRep.find({select:['id','currency','userid'],where:{userid:In(userid)}});
    if(info != null){
      info = Tools.formatData(info);
      info.map((item)=>{
        item.currency += num;
      })
      try {
        await userRep.save(info);
        return ErrCode.SYSTEM_SUCCESS;
      } catch (error) {
          return ErrCode.SYSTEM_FAIL;
      }
    }else{
      return ErrCode.USER_NOT_FOUND;
    }
  }
  /**减少 用户货币 */
  public async ReduceCurrency(userid:number,num:number):Promise<ErrCode>{
    let userRep:Repository<UserInfo> = await this.Repository({entities:UserInfo});
    let info:UserInfo = await userRep.findOne({where:{userid:userid}});
    if(info != null){
      info.currency -= num;
      try {
        await userRep.save(info);
        return ErrCode.SYSTEM_SUCCESS;
      } catch (error) {
        return ErrCode.SYSTEM_FAIL;
      }
    }
    return ErrCode.USER_NOT_FOUND;
  }

  /**添加 用户货币变动记录 */
  public async AddCurrencyUseLog(userid:number[],num:number,changeType:CurrencyLogType,append:any):Promise<any>{
    let rep:Repository<CurrencyLog> = await this.Repository({entities:CurrencyLog});
    if(rep){
        let list:CurrencyLog[] = [];
        userid.map((item)=>{
          let log:CurrencyLog = new CurrencyLog();
          log.currency = num;
          log.addtime = Tools.timestamp;
          log.status = CurrencyLogStatus.Sucdess;
          log.type =changeType;
          log.userid = item;
          log.append = append;
          log.remark = Constant.CurrencyLogType[changeType];
          list.push(log);
        });
        try {
            await rep.save(list);
            return ErrCode.SYSTEM_SUCCESS;
        } catch (error) {
            return ErrCode.SYSTEM_FAIL;
        }
    }else{
        return ErrCode.SYSTEM_FAIL;
    }
  }

}
